
#ifndef __REACTOR_H__
#define __REACTOR_H__
#include <iostream>
#include <unordered_map>
#include <memory>
#include "epoll.hpp"
#include "connection.hpp"

const int revs_num = 128;

class Reactor
{
private:
    bool ConnectionIsEmpty()
    {
        return _connections.empty();
    }
    bool IsInConnection(std::shared_ptr<Connection> conn)
    {
        auto it = _connections.find(conn->getFd());
        if (it == _connections.end())
        {
            return false;
        }
        return true;
    }
    bool IsInConnection(int sockfd)
    {
        auto it = _connections.find(sockfd);
        if (it == _connections.end())
        {
            return false;
        }
        return true;
    }
    int loopOnce(int timeout)
    {
        int n = _epoller->WaitEvents(_revs, revs_num, timeout);
        return n;
    }
    // 事件派发器
    void Dispatcher(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int sockfd = _revs[i].data.fd;     // 就绪的fd
            uint64_t events = _revs[i].events; // 就绪的事件

            // 将异常事件转化为IO错误
            if (events & EPOLLERR)
                events |= (EPOLLIN | EPOLLOUT);
            if (events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);

            if (events & EPOLLIN)
            {
                // 读事件就绪
                if (IsInConnection(sockfd))
                    _connections[sockfd]->Recv();
            }
            if (events & EPOLLOUT)
            {
                // 写事件就绪
                if (IsInConnection(sockfd))
                    _connections[sockfd]->Send();
            }
        }
    }
    void PrintConnection()
    {
        std::cout<<"当前Reactor正在管理的fd list:";
        for(auto& conn:_connections)
        {
            std::cout<<conn.first<<" ";
        }
        std::cout<<"\r\n";
    }
public:
    Reactor() : _isrunning(false), _epoller(std::make_unique<Epoller>()) {}
    ~Reactor() {}

    void loop()
    {
        if(ConnectionIsEmpty())
            return;
        
        int timeout=3000;
        _isrunning=true;
        while(_isrunning)
        {
            PrintConnection();
            int n=loopOnce(timeout);
            Dispatcher(n);
        }
        _isrunning=false;
    }
    // void start()
    // {
    //     _isrunning = true;
    //     while (_isrunning)
    //     {
    //         int timeout=1000;
    //         int n = _epoller->WaitEvents(_revs, revs_num, timeout);
    //         for (int i = 0; i < n; i++)
    //         {
    //             int sockfd = _revs[i].data.fd;     // 就绪的fd
    //             uint64_t events = _revs[i].events; // 就绪的事件

    //             // 将异常事件转化为IO错误
    //             if (events & EPOLLERR)
    //                 events |= (EPOLLIN | EPOLLOUT);
    //             if (events & EPOLLHUP)
    //                 events |= (EPOLLIN | EPOLLOUT);

    //             if (events & EPOLLIN)
    //             {
    //                 // 读事件就绪
    //                 if (IsInConnection(sockfd))
    //                     _connections[sockfd]->Recv();
    //             }
    //             if (events & EPOLLOUT)
    //             {
    //                 // 写事件就绪
    //                 if (IsInConnection(sockfd))
    //                     _connections[sockfd]->Send();
    //             }
    //         }
    //     }
    // }

    void AddConnection(std::shared_ptr<Connection> conn)
    {
        if (IsInConnection(conn))
            return;
        // 1.获取这个连接对应关心的事件
        uint32_t events = conn->GetEvents();
        int sockfd = conn->getFd();
        _epoller->AddEvent(sockfd, events);

        //设置当前conn对应的回指指针
        conn->SetOwner(this);
        // 2.将conn添加管理
        _connections[sockfd] = conn;
    }
    void stop()
    {
        _isrunning=false;
    }
    void EnableReadWrite(int sockfd,bool read,bool write)
    {
        if(!IsInConnection(sockfd))
        {
            LOG(LogLevel::ERROR)<<"connection is not exists:"<<sockfd;
            return;
        }

        //修改当前sockfd对应connection关心的事件
        uint32_t new_events=(EPOLLET)|(read?EPOLLIN:0)|(write?EPOLLOUT:0);
        _connections[sockfd]->SetEvent(new_events);

        //添加到epoll中
        _epoller->ModEvent(sockfd,new_events);
    }

    void DelConnection(int sockfd)
    {
        //从epoll中移除
        _epoller->DelEvent(sockfd);
        //从connection中移除
        _connections.erase(sockfd);
        //关闭sockfd
        close(sockfd);
        LOG(LogLevel::INFO)<<"client quit:"<<sockfd;
    }
private:
    // 1.epoll事件驱动
    std::unique_ptr<Epoller> _epoller;
    // 2.对连接的管理
    // fd和connection的映射
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    // 3.服务器是否运行标志
    bool _isrunning;

    // 就绪的事件
    struct epoll_event _revs[revs_num];
};
#endif